﻿using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.Mvvm.Messaging.Messages;
using HsServerHa.Common;
using HsServerHa.Common.TCP;
using HsServerHa.Core.Http;
using HsServerHa.Entity.Models;
using HsServerHa.Jobs;
using HsServerHa.Utility.Computer;
using HsServerHa.Utility.DataHelper;
using HsServerHa.Utility.HttpHelper;
using HsServerHa.Utility.NetWork;
using HsServerHa.Utility.SQLite;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Management;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace HsServerHa
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        public App()
        {
            //while (true)
            //{
            //    Thread.Sleep(1000);
            //}
            new SQLiteHelper();
            //处理加密
            if (string.IsNullOrEmpty(IniFileConfig.Current.GetStringValue("UserConfig", "PCKey")))
            {
                var dt = DateTime.Now.ToString("yyyyMMdd");
                var val = RegistryHelper.EncryptString(dt, RegistryHelper.key);
                IniFileConfig.Current.SetStringValue("UserConfig", "PCKey", val);
            }



            //注册应用程序异常回调
            DispatcherUnhandledException += App_DispatcherUnhandledException;
            //处理其他异常
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

            //启用Ping的IP回环功能（启用Ping）
            if (!NetWorkHelper.IsInboundRuleExists("Ha1433"))
            {
                NetWorkHelper.NetFwAddPorts("Ha1433", 1433);
            }

            //启用Ping的IP回环功能（启用Ping）
            if (!NetWorkHelper.IsInboundRuleExists("HaPing"))
            {
                NetWorkHelper.HandleCMDCommand("netsh advfirewall firewall add rule name=\"HaPing\" protocol=icmpv4:8,any dir=in action=allow");
            }

            //添加心跳6600入站规则
            if (!NetWorkHelper.IsInboundRuleExists("Ha心跳"))
            {
                NetWorkHelper.NetFwAddPorts("Ha心跳", 6600);
            }

            //添加Api6601入站规则
            if (!NetWorkHelper.IsInboundRuleExists("HaApi"))
            {
                NetWorkHelper.NetFwAddPorts("HaApi", 6601);
            }

            //添加文件同步6602入站规则
            if (!NetWorkHelper.IsInboundRuleExists("HaFileSync"))
            {
                NetWorkHelper.NetFwAddPorts("HaFileSync", 8384);
            }
            //添加文件同步6602入站规则
            if (!NetWorkHelper.IsInboundRuleExists("HaFileTCPSync"))
            {
                NetWorkHelper.NetFwAddPorts("HaFileTCPSync", 22000);
            }
            //添加文件同步6602入站规则
            if (!NetWorkHelper.IsInboundRuleExists("HaFileUDPSync"))
            {
                NetWorkHelper.NetFwAddPorts("HaFileUDPSync", 22000, "udp");
            }
            //添加文件同步6602入站规则
            if (!NetWorkHelper.IsInboundRuleExists("HaFileUDP21027Sync"))
            {
                NetWorkHelper.NetFwAddPorts("HaFileUDP21027Sync", 21027, "udp");
            }

            if (!string.IsNullOrEmpty(IniFileConfig.Current.GetStringValue("UserConfig", "IsMainPC")))
            {
                isMaster = bool.Parse(IniFileConfig.Current.GetStringValue("UserConfig", "IsMainPC"));
            }
            if (isMaster == null)
            {
                return;
            }
            initData();
        }

        /// <summary>
        /// 初始化数据
        /// </summary>
        public void initData()
        {
            //var sqlPro = "select * from ProgramManage";
            //var dtPro = DbHelperSQLite.Query(sqlPro)?.Tables?[0];
            //List<ProgramManageEntity> listPro= DataHelpers.ConvertToModel<ProgramManageEntity>(dtPro);

            List<ProgramManageEntity> listPro = SQLiteHelper.Table<ProgramManageEntity>().ToList();
            foreach (var item in listPro)
            {
                var proNames = item.Src.ToString().Split("\\");
                if (string.IsNullOrEmpty(item.Src))
                {
                    continue;
                }
                var ProcessNames = item.Src.ToString().Split("\\");
                var ProcessName = ProcessNames[ProcessNames.Length - 1].Replace(".exe", ""); ;
                Process[] MyProcess = Process.GetProcessesByName(ProcessName);
                foreach (var p in MyProcess)
                {
                    p.Kill();
                }
            }


            //var sqlBind = "select * from MasterSlaveBind";
            //var dtBind = DbHelperSQLite.Query(sqlBind)?.Tables?[0];
            //List<MasterSlaveBindEntity> listBind = DataHelpers.ConvertToModel<MasterSlaveBindEntity>(dtBind);
            List<MasterSlaveBindEntity> listBind = SQLiteHelper.Table<MasterSlaveBindEntity>().ToList();

            //var sqlVM = "select * from VirtuallyManage";
            //var dt = DbHelperSQLite.Query(sqlVM)?.Tables?[0];
            //List<VirtuallyManageEntity> list = DataHelpers.ConvertToModel<VirtuallyManageEntity>(dt);

            List<VirtuallyManageEntity> list = SQLiteHelper.Table<VirtuallyManageEntity>().ToList();

            var isSwitch = false;
            if (isMaster.Value)
            {
                Task.Run(() =>
                {
                    var bindFirst = listBind?.FirstOrDefault();
                    if (bindFirst == null)
                    {
                        IniFileConfig.Current.SetStringValue("UserConfig", "IsMainPC", "");
                        return;
                    }
                    if (string.IsNullOrEmpty(bindFirst.SlaveIP))
                    {
                        return;
                    }
                    //查询从机是否也是主机配置
                    var slavePath = $"http://{bindFirst.SlaveIP}:{ConfigurationManager.AppSettings["HttpPort"]?.ToString() ?? "6601"}/";
                    var slaveInfo = HttpHelpers.Get<HttpResponseResultModel<MasterSlaveBindEntity>>(slavePath + ConfigurationManager.AppSettings["getSlaveInfo"]?.ToString() ?? "getSlaveInfo").Result;
                    if (slaveInfo != null)
                    {
                        if (slaveInfo.IsSuccess && slaveInfo.BackResult != null)
                        {
                            if (slaveInfo.BackResult.IsMaster == "true")
                            {//将主切换成从
                                App.isMaster = false;
                                App.MasterIP = slaveInfo.BackResult.MasterIP;
                                App.socketServer = null;
                                App.proxSocket = null;
                                IniFileConfig.Current.SetStringValue("UserConfig", "IsMainPC", "false");
                                DbHelperSQLite.ExecuteSql($"update MasterSlaveBind set MasterIP='{slaveInfo.BackResult.MasterIP}',SlaveIP='{bindFirst.MasterIP}',IsMaster='false' ");

                                //dtBind = DbHelperSQLite.Query(sqlBind)?.Tables?[0];
                                listBind = SQLiteHelper.Table<MasterSlaveBindEntity>().ToList();

                                var msFirst = list?.FirstOrDefault();
                                if (msFirst != null)
                                {
                                    //切换网络
                                    //var cmd = $"/c" +
                                    //    $" netsh interface ip set address name={msFirst.NetworkCardName} source=static address={msFirst.CurrIP} mask={msFirst.SubnetMask} gateway={msFirst.Gateway}" +
                                    //    $"& netsh interface ipv4 delete address name={msFirst.NetworkCardName}  addr={msFirst.VirtuallyIP}  gateway=all ";
                                    //NetWorkHelper.HandleCMDCommand(cmd);
                                    NetWorkHelper.DeleteVirtualIP(msFirst.VirtuallyIP);
                                    LoggerHelper.SetInfo("重启后检测到从机切换成主机，自动从主机切换成从机", "系统监测");
                                    isSwitch = true;

                                    if (list.Count > 0)
                                    {

                                        CurrIP = list[0].CurrIP;
                                        if (listBind.Count > 0)
                                        {

                                            MasterIP = listBind[0].MasterIP;
                                            GatewayIP = list[0].Gateway;
                                            ReferIP = list[0].ReferIP;
                                            VirtuallyIP = list[0].VirtuallyIP;
                                            //var dtXt = DbHelperSQLite.Query("select * from  HeartManage where IsLocal='true'")?.Tables?[0];

                                            var listXt = SQLiteHelper.Table<HeartEntity>().Where(x => x.IsLocal == "true").ToList();
                                            //查询心跳
                                            if (listXt.Count > 0)
                                            {

                                                if (isMaster != null)
                                                {
                                                    if (isMaster.Value)
                                                    {
                                                        XtIP = listXt[0].HeartIP;
                                                    }
                                                    else
                                                    {
                                                        XtIP = listXt[0].MasterHeartIPBind;
                                                    }

                                                }

                                            }

                                        }

                                    }

                                    return;
                                }

                            }
                        }
                    }
                });

            }

            if (list.Count > 0)
            {

                CurrIP = list[0].CurrIP;
                if (listBind.Count > 0)
                {

                    MasterIP = listBind[0].MasterIP;
                    GatewayIP = list[0].Gateway;
                    ReferIP = list[0].ReferIP;
                    VirtuallyIP = list[0].VirtuallyIP;
                    //var dtXt = DbHelperSQLite.Query("select * from  HeartManage where IsLocal='true'")?.Tables?[0];

                    var listXt = SQLiteHelper.Table<HeartEntity>().Where(x => x.IsLocal == "true").ToList();
                    //查询心跳
                    if (listXt.Count > 0)
                    {
                        //var listXt = DataHelpers.ConvertToModel<HeartEntity>(dtXt);
                        if (isMaster != null)
                        {
                            if (isMaster.Value)
                            {
                                XtIP = listXt[0].HeartIP;
                            }
                            else
                            {
                                XtIP = listXt[0].MasterHeartIPBind;
                            }

                        }

                    }

                }

            }
        }

        /// <summary>
        /// 处理线程其他异常
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            Exception ex = e.ExceptionObject as Exception;

            LoggerHelper.Error(ex.Message+ex.ToString());
            LoggerHelper.Error(ex.StackTrace);
        }

        /// <summary>
        /// 处理UI线程异常
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            LoggerHelper.Error(e.Exception.Message+e.ToString());
            LoggerHelper.Error(e.Exception.StackTrace);
        }

        public static CancellationTokenSource source = new CancellationTokenSource();

        /// <summary>
        ///单例处理
        /// </summary>
        SingleInstance _singleInstance = new SingleInstance()
        {
            ApplicationName = ConfigurationManager.AppSettings["ApplicationName"],
            WindowName = ConfigurationManager.AppSettings["WindowName"]
        };
        protected async override void OnStartup(StartupEventArgs e)
        {
            //检查当前实例
            _singleInstance.CheckApplicationMutex();
            WeakReferenceMessenger.Default.Register<ValueChangedMessage<string>, string>(this, "SwitchMasterSlave", (r, message) =>
            {
                if (message != null)
                {
                    if (message.Value == "Slave")
                    {
                        MasterSlaveSwitchHelper.SwitchSlave();
                    }
                    else
                    {
                        MasterSlaveSwitchHelper.SwitchMaster();
                    }
                }
            });
            WeakReferenceMessenger.Default.Register<ValueChangedMessage<string>, string>(this, "InitSys", (r, message) =>
            {
                if (message != null)
                {
                    if (message.Value == "InitSys")
                    {
                        InitSysSettingHelper.InitSys();
                    }
                }
            });
            base.OnStartup(e);
            Task.Run(() =>
            {
                StartSocket();
            });
            var TriggerState = QuartzHelper.Instance.StartJobExecuteByCron<RecurringTaskJob>("*/2 * * * * ?", "循环执行任务");
            var TriggerState1 = QuartzHelper.Instance.StartJobExecuteByCron<CheckXtNumTaskJob>("*/2 * * * * ?", "监听心跳超时次数");
            var TriggerState2 = QuartzHelper.Instance.StartJobExecuteByCron<CheckSQLTaskJob>("*/5 * * * * ?", "监听数据库主从镜像");
            var TriggerState3 = QuartzHelper.Instance.StartJobExecuteByCron<CheckChildNetworkJob>("*/10 * * * * ?", "监听所有子网卡");
            var TriggerState4 = QuartzHelper.Instance.StartJobExecuteByCron<CheckProgramTaskJob>("*/10 * * * * ?", "监听所有代理程序");
            //var TriggerState5 = QuartzHelper.Instance.StartJobExecuteByCron<CheckFilesSyncTaskNewJob>("*/10 * * * * ?", "监听文件同步");

            //// 查询进程创建 1秒钟通知
            //var qCreate = new WqlEventQuery($"__InstanceCreationEvent", TimeSpan.FromSeconds(1), $"TargetInstance isa \"Win32_Process\" and TargetInstance.Name = 'HsServerHa.exe'");

            //// 查询进程关闭 1秒钟通知
            //var qDelete = new WqlEventQuery($"__InstanceDeletionEvent", TimeSpan.FromSeconds(1), $"TargetInstance isa \"Win32_Process\" and TargetInstance.Name = 'HsServerHa.exe'");

            //// 创建事件查询的监听器
            //ManagementEventWatcher wCreate = new ManagementEventWatcher(qCreate);
            //ManagementEventWatcher wDelete = new ManagementEventWatcher(qDelete);
            //// 注册事件
            //wCreate.EventArrived += (sender, e) =>
            //{
            //    Console.WriteLine($"进程启动：{GetInfo(e.NewEvent)}");
            //};

            //wDelete.EventArrived += (sender, e) =>
            //{
            //    Console.WriteLine($"进程关闭：{CloseInfo(e.NewEvent)}");
            //};

            //// 开始监听
            //wCreate.Start();
            //wDelete.Start();


            return;
            //暂时不用
            if (e.Args.Length < 1)
            {
                Application.Current.ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown;

                //守护进程互斥量
                mutex_deamon = new System.Threading.Mutex(true, "MUTEX_DEAMON");
                if (mutex_deamon.WaitOne(0, false))
                {
                    RunMonitorTimer();

                    // 显示一个自定义窗体，非主窗体，用于阻塞进程，窗体关闭后，守护进程将关闭
                    WndDeamon wnd = new WndDeamon();
                    wnd.ShowDialog();

                    this.Shutdown();
                }
                else
                {
                    MessageBox.Show("程序已经在运行！", "提示");
                    this.Shutdown();
                }
            }
            else
            {
                isMain = true;
                mutex_main = new System.Threading.Mutex(true, "MUTEX_MAIN");
                if (mutex_main.WaitOne(0, false))
                {
                    RunMonitorTimer();

                    base.OnStartup(e);
                    Application.Current.ShutdownMode = ShutdownMode.OnMainWindowClose;
                }
                else
                {
                    Application.Current.ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown;
                    MessageBox.Show("程序已经在运行！", "提示");
                    this.Shutdown();
                }
            }

        }

        static string GetInfo(ManagementBaseObject obj)
        {
            var instance = obj["TargetInstance"] as ManagementBaseObject;
            var name = instance["Name"];
            var processId = instance["ProcessId"];
            return $"{instance["Name"]}-{instance["ProcessId"]}";
        }

        static string CloseInfo(ManagementBaseObject obj)
        {
            var instance = obj["TargetInstance"] as ManagementBaseObject;
            var name = instance["Name"];
            var processId = instance["ProcessId"];
            return $"{instance["Name"]}-{instance["ProcessId"]}";
        }


        #region 业务参数及函数
        public static byte[] acceptData = new byte[1 * 1024];
        public static byte[] sendData = Encoding.ASCII.GetBytes("1");

        public static List<Process> ProcessList = new List<Process>();

        public static bool isLogin = false;
        /// <summary>
        /// 当前本机IP
        /// </summary>
        public static string CurrIP { get; set; }
        /// <summary>
        /// 主机IP
        /// </summary>
        public static string MasterIP { get; set; }

        /// <summary>
        /// 虚拟IP
        /// </summary>
        public static string VirtuallyIP { get; set; }

        /// <summary>
        /// 是否Ping的通虚拟IP
        /// </summary>
        public static bool IsPingVirtuallyIP { get; set; }

        /// <summary>
        /// 主机心跳
        /// </summary>
        public static string XtIP { get; set; }
        public static bool XtIsOpen { get; set; }

        /// <summary>
        /// 网关IP
        /// </summary>
        public static string GatewayIP { get; set; }

        /// <summary>
        /// 参考IP
        /// </summary>
        public static string ReferIP { get; set; }

        /// <summary>
        /// 心跳超时次数
        /// </summary>
        public static int XtDisconnectNum { get; set; } = 0;

        /// <summary>
        /// 最大心跳超时次数
        /// </summary>
        public static int MaxXtDisconnectNum { get; set; } = 5;

        public static bool IsEntrustMaster { get; set; } = false;

        /// <summary>
        /// 网关IP是否是通的
        /// </summary>
        public static bool IsPingGateway { get; set; }

        /// <summary>
        /// 参考IP是否是通的
        /// </summary>
        public static bool IsPingRefer { get; set; }

        /// <summary>
        /// 是否是主机
        /// </summary>
        public static bool? isMaster { get; set; } = null;
        public async static void StartSocket()
        {
            var isMainPC = IniFileConfig.Current.GetStringValue("UserConfig", "IsMainPC");
            if (string.IsNullOrEmpty(isMainPC))
            {

            }
            else
            {
                isMaster = bool.Parse(isMainPC);
                if (isMaster.Value)
                {
                    TCPServerHelper.InitiateHeart(source.Token, socketServer, XtIP);
                }
                else
                {
                    //查询主机心跳IP


                    TCPClientHelper.SockerClient(source.Token, socketServer);
                }
            }
        }
        public void SockerServer()
        {
            Task.Run(() =>
            {
                TCPServerHelper.InitiateHeart(source.Token, socketServer, XtIP);
            }, source.Token);
        }

        public static Socket socketServer;
        /// <summary>
        /// 通信专用
        /// </summary>
        public static Socket proxSocket { get; set; }

        /// <summary>
        /// 文件同步Socket
        /// </summary>
        public static TcpClient fileTcpClient { get; set; }

        public static bool IsStartSync = false;
        #endregion

        protected override void OnExit(ExitEventArgs e)
        {
            LoggerHelper.Info("<<<======================End");
            Process.GetCurrentProcess().Kill();
            base.OnExit(e);
        }


        #region 守护进程
        /// <summary>
        /// 主进程互斥量
        /// </summary>
        private static System.Threading.Mutex mutex_main;

        /// <summary>
        /// 守护进程互斥量
        /// </summary>
        private static System.Threading.Mutex mutex_deamon;

        /// <summary>
        /// 是否为主进程
        /// </summary>
        private static bool isMain = false;

        /// <summary>
        /// 打开监视定时器
        /// </summary>
        public void RunMonitorTimer()
        {
            System.Timers.Timer timer = new System.Timers.Timer();
            timer.Elapsed += timer_Elapsed;
            timer.Interval = 2000;
            timer.Start();
        }

        /// <summary>
        /// 打开程序
        /// </summary>
        /// <param name="arg">参数不为null时打开主进程，否则打开守护进程</param>
        public void RunProcess(string arg = null)
        {
            /* 运行程序，不带参数，打开守护进程 */
            Process m_Process = new Process();
            m_Process.StartInfo.FileName = Process.GetCurrentProcess().MainModule.FileName;
            m_Process.StartInfo.Arguments = arg;
            m_Process.Start();
        }
        void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (!isMain)
            {
                if (mutex_main == null)
                {
                    mutex_main = new System.Threading.Mutex(true, "MUTEX_MAIN");
                }
                if (mutex_main.WaitOne(0, false))
                {
                    //必须释放mutex，否则将导致mutex被占用，主程序不能允许
                    mutex_main.Dispose();
                    mutex_main = null;

                    RunProcess("main");
                }
            }
            else
            {
                if (mutex_deamon == null)
                {
                    mutex_deamon = new System.Threading.Mutex(true, "MUTEX_DEAMON");
                }
                if (mutex_deamon.WaitOne(0, false))
                {
                    mutex_deamon.Dispose();
                    mutex_deamon = null;

                    RunProcess();
                }
            }
        }

        #endregion
    }
}
